/*
客户端（默认端口8080）：
- 接收命令行参数：[port] [count] [x]
- 连接到指定端口的服务器
- 循环发送count次double x到服务器，接收double result
- 打印每次服务耗时rtt_us，以及平均耗时avg_rtt_us
*/

#include <unistd.h>
#include <arpa/inet.h>
#include <sys/time.h>

int main(int argc, char** argv) {
    // 默认连接线程服务器端口8080；可通过命令行参数覆盖
    int port = 8080; // default thread server
    int count = 1;   // 默认请求次数1
    double x = 5.0;  // 默认计算输入5.0
    const char* host = "127.0.0.1"; // 默认本地回环地址
    // 用法：client [port] [count] [x]
    if (argc > 1) port = atoi(argv[1]);
    if (argc > 2) count = atoi(argv[2]);
    if (argc > 3) x = atof(argv[3]);

    double result;
    // 目标服务器地址配置（IPv4 + 端口）
    struct sockaddr_in serv_addr = {0};
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(port);
    serv_addr.sin_addr.s_addr = inet_addr(host);

    struct timeval s, e;
    long long total_rtt_us = 0;
    for (int i = 0; i < count; ++i) {
        // 每次请求新建一次连接：服务器采用“一次连接一次服务”模型
        int sock = socket(AF_INET, SOCK_STREAM, 0);
        if (sock < 0) {
            perror("socket");
            return 1;
        }
        // 连接服务器
        if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
            perror("connect");
            close(sock);
            return 1;
        }
        // 记录起始时间，发送x并同步等待结果
        gettimeofday(&s, NULL);
        write(sock, &x, sizeof(double));
        if (read(sock, &result, sizeof(double)) != sizeof(double)) {
            perror("read");
        }
        // 记录结束时间并计算RTT
        gettimeofday(&e, NULL);
        long long rtt_us = (e.tv_sec - s.tv_sec) * 1000000LL + (e.tv_usec - s.tv_usec);
        total_rtt_us += rtt_us;
        // 打印每次请求结果与RTT
        printf("[%d] F(%.2f) = %.2f, rtt_us=%lld\n", i+1, x, result, rtt_us);
        // 关闭本次连接
        close(sock);
    }
    if (count > 0) {
        // 打印平均RTT
        printf("avg_rtt_us=%.2f (count=%d)\n", (double)total_rtt_us / (double)count, count);
    }
}
